/*
    Selection.cpp

    Date:
        05-11-10

    Descripton:
        Static class to determine what item is being selected
        at (x, y) screen-coordinates

    Authors:
        Nathaniel Brown
        Subodh Prabhu
        Jesus Suarez
*/


/****************************************************************************/
/*                              I N C L U D E S                             */
/****************************************************************************/

#include <cmath>
#include <list>
#include "Selection.h"
#include "Events.h"
#include "Clock.h"
#include "Defines.h"


/****************************************************************************/
/*                               E X T E R N S                              */
/****************************************************************************/

extern Events events;
extern Item * selectedItem;
extern Clock clk;


/****************************************************************************/
/*       S E L E C T I O N   :   S T A T I C   D A T A   M E M B E R S      */
/****************************************************************************/

double Selection::angle;

double Selection::dist_rad;

double Selection::relative_x;

double Selection::relative_y;

time_t Selection::select_time;

int Selection::select_priority;


/****************************************************************************/
/*          S E L E C T I O N   :   M E M B E R   F U N C T I O N S         */
/****************************************************************************/

bool
Selection::checkBounds(double x, double y) {
  relative_x = x - SCREEN_W / 2;
  relative_y = SCREEN_H / 2 - y;
  dist_rad = sqrt(relative_x * relative_x + relative_y * relative_y);
  
  if(dist_rad > CLOCK_RAD * EVENT_OUT)
    return false;

  angle = atan2(relative_y, relative_x);
  return true;
}

void
Selection::convertToTime() {
  double hour = 3.0 - 6.0 * angle / PI;
  double hour_diff = hour - clk.getTime();
  if(hour_diff < 0)
    hour_diff += 12;

  select_time = time(NULL) + (time_t) (hour_diff * 3600);
}

bool
Selection::getPriority() {
  if(   dist_rad > CLOCK_RAD * TASK_IN
     && dist_rad < CLOCK_RAD * TASK_OUT) {
       select_priority = TASK;
       return true;
  }
  if(   dist_rad > CLOCK_RAD * FUN_TIME_IN
     && dist_rad < CLOCK_RAD * FUN_TIME_OUT) {
       select_priority = FUN_TIME;
       return true;
  }
  if(   dist_rad > CLOCK_RAD * EVENT_IN
     && dist_rad < CLOCK_RAD * EVENT_OUT) {
       select_priority = EVENT;
       return true;
  }
  if(   dist_rad > CLOCK_RAD * APPOINTMENT_IN
     && dist_rad < CLOCK_RAD * APPOINTMENT_OUT) {
       select_priority = APPOINTMENT;
       return true;
  }
  return false;
}

bool
Selection::checkEvents() {
  list<Item> & items = events.items;
  list<Item>::reverse_iterator it;
  for(it = items.rbegin(); it != items.rend(); ++it) {
    double start_diff = difftime(select_time, ((Item)*it).getStartTime());
    double end_diff = difftime(((Item)*it).getEndTime(), select_time);
    if(start_diff > 0 && end_diff > 0) {
      if(((Item)*it).getLevel() == select_priority) {
        selectedItem = &((Item)*it);
        return true;
      }
    }
  }
  return false;
}

bool
Selection::getSelectedItem(double x, double y) {
  if(!checkBounds(x, y))
    return false;
  convertToTime();
  if(!getPriority())
    return false;
  return checkEvents();
}